﻿Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography

Namespace Utilities
    ''' <summary>
    ''' Class utility to generate HashCode for Cache support.
    ''' </summary>
    ''' <remarks></remarks>
    Friend NotInheritable Class HashGenerator

        Private Sub New()
        End Sub

        ''' <summary>
        ''' Generates the key for a generic object.
        ''' </summary>
        ''' <param name="sourceObject">The source object. Must be serializable.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function GenerateKey(sourceObject As Object) As String
            If sourceObject Is Nothing Then Throw New ArgumentNullException("SourceObject cannot be nothing!")
            Dim hashString As String = Nothing
            Try
                hashString = ComputeHash(ObjectToByteArray(sourceObject))
            Catch ex As Exception

            End Try
            Return hashString
        End Function

        Private Shared Function ComputeHash(objectAsBytes As Byte()) As String
            Dim md5 As MD5 = New MD5CryptoServiceProvider()
            Try
                Dim result = md5.ComputeHash(objectAsBytes)
                Dim hashStr = (From b In result
                            Select b.ToString("X2")).Aggregate(Function(a, b) String.Concat(a, b))
                Return hashStr
            Catch ex As ArgumentNullException
                Return Nothing
            End Try
        End Function

        Private Shared ReadOnly locker As New Object()

        Private Shared Function ObjectToByteArray(objectToSerialize As Object) As Byte()
            Dim fs = New MemoryStream()
            Dim formatter = New BinaryFormatter()
            Try
                SyncLock (locker)
                    formatter.Serialize(fs, objectToSerialize)
                End SyncLock
                Return fs.ToArray()
            Catch ex As SerializationException
                Return Nothing
            Finally
                fs.Close()
            End Try
        End Function
    End Class
End Namespace
